#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> 
#include <sys/time.h> 
#include "alarm.h"

#define UDP_PORT 53
#define SERVER_FILE "dns_servers.conf"

typedef unsigned short int u16;
struct Packet{
	struct Header* header;
	struct Question* question;
	struct Answer* answer;
	struct Answer* authority;
	struct Answer* additional;
	char* message;	
};

struct Header{
	u16 id;
	u16 options;
	u16 qdcount;
	u16 ancount;
	u16 nscount;
	u16 arcount;
};
struct Question{
	char* qname;
	u16 qtype;
	u16 qclass;
};
/**
	Definitie pentru Resource record
**/
struct Answer{
	char* name;
	u16 type;
	u16 clasa;
	int ttl;
	u16 rdlength;
	char* rdata;	
};
//folosit la alarm pentru a vedea daca s-a produs sau nu o alarma
const int* was_timeout;
/**
	Afiseaza un mesaj de eroare si iese din program
**/
void die(char* message);
/**
	Wrapper peste calloc care afiseaza o eroare in caz ca nu se poate aloca memorie
**/
void* mycalloc(int n, int size);
/**
	Creaza un nou pachet de query
**/
struct Packet* newQuery(u16 id, int opcode, char* domain, u16 type, u16 clasa);
/**
	Deschide un socket si face bind pentru a asculta pentru un mesaj de raspuns 
	de la server
**/
void conectare(char* ipadr, int* send_sock, int* receive_sock, struct sockaddr_in* remoteServAddr);
/**
	Trimite pachetul de query
**/
void sendPacket(struct Packet* pack, int sd, struct sockaddr_in* remoteServAddr);
/**
	Primeste si realizeaza prelucrarea pachetelor primite de la server
**/
struct Packet* receivePacket(int rc);

/**
	Afiseaza raspunsul de la server intr-un mod asemanator lui dig
**/
void printResponse(struct Packet* pack, char* domain);
/**
	Intoarce valoarea prelucrata din campul rdata
**/
char* value(struct Answer* ans, struct Packet* pack);

/**
	Realizeaza "decompresia", cauta ce mai trebuie adaugat sirului in mesajul initial citit
**/
char *decompress(char* buff, int i, int *f);
char *strrev(char* str);
